package leveldb

import (
	"sync"

	Log "github.com/cihub/seelog"
	"github.com/syndtr/goleveldb/leveldb"
)

var (
	createLock      = &sync.Mutex{}            //创建用锁
	syncTablekeyMap = map[string]*sync.Mutex{} //序列锁集合
)

/**
 * 保存数据
 * @param dbName 数据库名称
 * @param key 键
 * @param value 值
 * @return error 错误信息
 */
func Save(dbName, key, value string) error {
	lock, ok := syncTablekeyMap[dbName]
	if !ok {
		createLock.Lock() //加锁
		lock = &sync.Mutex{}
		syncTablekeyMap[dbName] = lock
		createLock.Unlock() //解锁
	}

	lock.Lock()         //加锁
	defer lock.Unlock() //解锁

	db, err := leveldb.OpenFile(dbName, nil)
	if err != nil {
		Log.Error("打开数据库发生异常:", err)
		return err
	}
	defer db.Close() // 确保数据库在使用完毕后关闭

	err = db.Put([]byte(key), []byte(value), nil)
	if err != nil {
		Log.Error("保存数据发生异常:", err)
		return err
	}

	return nil
}

/**
 * 读取数据
 * @param dbName 数据库名称
 * @param key 键
 * @return string,error 值,错误信息
 */
func Read(dbName, key string) (string, error) {
	lock, ok := syncTablekeyMap[dbName]
	if !ok {
		createLock.Lock() //加锁
		lock = &sync.Mutex{}
		syncTablekeyMap[dbName] = lock
		createLock.Unlock() //解锁
	}

	lock.Lock()         //加锁
	defer lock.Unlock() //解锁

	db, err := leveldb.OpenFile(dbName, nil)
	if err != nil {
		Log.Error("打开数据库发生异常:", err)
		return "", err
	}
	defer db.Close() // 确保数据库在使用完毕后关闭

	value, err := db.Get([]byte("name"), nil)
	if err != nil {
		Log.Error("读取数据发生异常:", err)
		return "", err
	}

	return string(value), nil
}

/**
 * 删除数据
 * @param dbName 数据库名称
 * @param key 键
 * @return error 错误信息
 */
func Del(dbName, key string) error {
	lock, ok := syncTablekeyMap[dbName]
	if !ok {
		createLock.Lock() //加锁
		lock = &sync.Mutex{}
		syncTablekeyMap[dbName] = lock
		createLock.Unlock() //解锁
	}

	lock.Lock()         //加锁
	defer lock.Unlock() //解锁

	db, err := leveldb.OpenFile(dbName, nil)
	if err != nil {
		Log.Error("打开数据库发生异常:", err)
		return err
	}
	defer db.Close() // 确保数据库在使用完毕后关闭

	err = db.Delete([]byte(key), nil)
	if err != nil {
		Log.Error("删除数据发生异常:", err)
		return err
	}

	return nil
}

/**
 * 检查键是否存在
 * @param dbName 数据库名称
 * @param key 键
 * @return bool,error 键是否存在,错误信息
 */
func HasKey(dbName, key string) (bool, error) {
	lock, ok := syncTablekeyMap[dbName]
	if !ok {
		createLock.Lock() //加锁
		lock = &sync.Mutex{}
		syncTablekeyMap[dbName] = lock
		createLock.Unlock() //解锁
	}

	lock.Lock()         //加锁
	defer lock.Unlock() //解锁

	db, err := leveldb.OpenFile(dbName, nil)
	if err != nil {
		Log.Error("打开数据库发生异常:", err)
		return false, err
	}
	defer db.Close() // 确保数据库在使用完毕后关闭

	hasKey, err := db.Has([]byte(key), nil)
	if err != nil {
		Log.Error("'检查键是否存在'发生异常:", err)
		return false, err
	}

	return hasKey, nil
}

/**
 * 列出数据库所有键值对
 * @param dbName 数据库名称
 * @return map error 键值对,错误信息
 */
func FindAll(dbName string) (map[string]string, error) {
	lock, ok := syncTablekeyMap[dbName]
	if !ok {
		createLock.Lock() //加锁
		lock = &sync.Mutex{}
		syncTablekeyMap[dbName] = lock
		createLock.Unlock() //解锁
	}

	lock.Lock()         //加锁
	defer lock.Unlock() //解锁

	db, err := leveldb.OpenFile(dbName, nil)
	if err != nil {
		Log.Error("打开数据库发生异常:", err)
		return nil, err
	}
	defer db.Close() // 确保数据库在使用完毕后关闭

	iter := db.NewIterator(nil, nil)
	defer iter.Release()

	result := make(map[string]string)
	for iter.Next() {
		key := string(iter.Key())
		value := string(iter.Value())
		result[key] = value
	}

	if err := iter.Error(); err != nil {
		Log.Error("遍历键值对发生异常:", err)
		return nil, err
	}

	return result, nil
}
